#include "database_manager.h"
#include <QSqlQuery>
#include <QSqlRecord>
#include <QStandardPaths>
#include <QDir>
#include <QJsonDocument>
#include <QJsonObject>
#include "../global_logger.h"

/**
 * @brief 构造函数
 * @param parent 父对象指针
 */
DatabaseManager::DatabaseManager(QObject *parent)
    : QObject(parent)
{
}

/**
 * @brief 析构函数
 * 关闭数据库连接（如果已打开）
 */
DatabaseManager::~DatabaseManager()
{
    if (m_db && m_db->isOpen()) {
        m_db->close();
    }
}

/**
 * @brief 初始化数据库
 * 根据数据库名称确定数据库路径，并打开数据库连接
 * @param databaseName 数据库文件名，如果为空或":memory:"则使用特殊路径
 * @return 初始化成功返回true，否则返回false
 */
bool DatabaseManager::initialize(const QString &databaseName)
{
    QString dbPath;
    if (databaseName.isEmpty() || databaseName == ":memory:") {
        dbPath = databaseName;
    } else {
        // 使用当前目录下的 data/db 目录
        QString dataPath = "data/db";
        QDir dir;
        if (!dir.exists(dataPath)) {
            dir.mkpath(dataPath);
        }
        dbPath = dataPath + "/" + databaseName;
    }
    LOG_INFO("数据库初始化路径 {}:",dbPath.toStdString());
    return openDatabase(dbPath);
}

/**
 * @brief 打开数据库连接
 * 创建SQLite数据库连接并尝试打开
 * @param databasePath 数据库文件路径
 * @return 打开成功返回true，否则返回false
 */
bool DatabaseManager::openDatabase(const QString &databasePath)
{
    m_db = std::make_unique<QSqlDatabase>(QSqlDatabase::addDatabase("QSQLITE"));
    m_db->setDatabaseName(databasePath);
    
    if (!m_db->open()) {
        m_lastError = m_db->lastError().text();
       LOG_ERROR("无法打开数据库 {}:",m_lastError.toStdString());
        return false;
    }
    
    return true;
}

/**
 * @brief 检查指定的表是否存在于数据库中
 *
 * 该函数通过查询SQLite系统表sqlite_master来确定指定名称的表是否存在。
 *
 * @param tableName 要检查的表名
 * @return 如果表存在返回true，否则返回false
 * @note 如果数据库未初始化或查询执行失败，函数会返回false，
 *       并通过lastError()函数可以获取具体的错误信息
 */
bool DatabaseManager::tableExists(const QString &tableName)
{
    if (!m_db || !m_db->isOpen()) {
        m_lastError = "数据库未初始化";
        return false;
    }
    
    QSqlQuery query(*m_db);
    query.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?");
    query.addBindValue(tableName);
    
    if (!query.exec()) {
        m_lastError = query.lastError().text();
        return false;
    }
    
    return query.next();
}

/**
 * @brief 创建数据库表
 * @param tableName 要创建的表名
 * @param columnsDefinition 表的列定义字符串
 * @return 创建成功返回true，失败返回false
 *
 * 该函数会先检查表是否已存在，如果不存在则创建指定的数据库表。
 * 使用"CREATE TABLE IF NOT EXISTS"语句确保即使表已存在也不会报错。
 */
bool DatabaseManager::createTable(const QString &tableName, const QString &columnsDefinition)
{
    // 检查数据库连接状态
    if (!m_db || !m_db->isOpen()) {
        m_lastError = "数据库未初始化";
        return false;
    }

    // 先检查表是否已存在，避免不必要的SQL执行
    if (tableExists(tableName)) {
        return true;
    }

    QString sql = QString("CREATE TABLE IF NOT EXISTS %1 (%2)").arg(tableName, columnsDefinition);
    
    // 执行SQL语句创建表
    QSqlQuery query(*m_db);
    if (!query.exec(sql)) {
        m_lastError = query.lastError().text();
        LOG_ERROR("创建表失败 {}:",m_lastError.toStdString());
        return false;
    }
    
    return true;
}

/**
 * @brief 在指定表中插入或更新数据
 *
 * 此函数使用"INSERT OR REPLACE"策略将数据插入到数据库表中。
 * 如果主键已存在，则更新现有记录；否则插入新记录。
 *
 * @param tableName 目标表名
 * @param data 包含列名和对应值的映射数据
 * @param primaryKey 用作主键的列名（用于判断记录是否存在）
 * @return bool 操作成功返回true，失败返回false
 *
 * @note 操作失败时错误信息存储在m_lastError成员变量中
 */
bool DatabaseManager::insertOrUpdate(const QString &tableName, const QVariantMap &data, const QString &primaryKey)
{
    Q_UNUSED(primaryKey); // 明确标记参数未使用以消除警告

    if (!m_db || !m_db->isOpen()) {
        m_lastError = "数据库未初始化";
        return false;
    }
    
    if (data.isEmpty()) {
        m_lastError = "数据为空";
        return false;
    }
    
    // 构建列名和值
    QStringList columns;
    QStringList placeholders;
    QVariantList values;
    
    for (auto it = data.constBegin(); it != data.constEnd(); ++it) {
        columns << it.key();
        placeholders << "?";
        values << it.value();
    }
    
    // 构建SQL语句
    QString sql = QString("INSERT OR REPLACE INTO %1 (%2) VALUES (%3)")
                     .arg(tableName, columns.join(", "), placeholders.join(", "));
    
    QSqlQuery query(*m_db);
    query.prepare(sql);
    
    for (const QVariant &value : values) {
        query.addBindValue(value);
    }
    
    if (!query.exec()) {
        m_lastError = query.lastError().text();
        LOG_ERROR("插入或更新数据失败 {}:",m_lastError.toStdString());
        return false;
    }
    
    return true;
}

/**
 * @brief 从指定表中查询满足条件的第一条记录
 *
 * 该函数根据给定的表名和查询条件，在数据库中查找第一条匹配的记录。
 * 如果查询成功且找到匹配记录，则返回包含该记录所有字段的键值对映射；
 * 否则返回空的QVariantMap。
 *
 * @param tableName 要查询的表名
 * @param conditions 查询条件，以字段名为键、字段值为值的键值对映射
 * @return 包含查询结果记录的QVariantMap，如果未找到记录或查询失败则返回空映射
 *
 * @note 如果数据库未初始化或查询执行失败，可通过lastError()获取具体错误信息
 */
QVariantMap DatabaseManager::selectRecord(const QString &tableName, const QVariantMap &conditions)
{
    QVariantMap result;
    
    // 检查数据库连接状态
    if (!m_db || !m_db->isOpen()) {
        m_lastError = "数据库未初始化";
        return result;
    }
    
    QString whereClause = buildWhereClause(conditions);
    QString sql = QString("SELECT * FROM %1").arg(tableName);
    if (!whereClause.isEmpty()) {
        sql += " WHERE " + whereClause;
    }
    sql += " LIMIT 1";
    
    QSqlQuery query(*m_db);
    query.prepare(sql);
    
    int index = 0;
    for (auto it = conditions.constBegin(); it != conditions.constEnd(); ++it) {
        query.bindValue(index++, it.value());
    }
    
    if (!query.exec()) {
        m_lastError = query.lastError().text();
        LOG_ERROR("查询数据失败 {}:",m_lastError.toStdString());
        return result;
    }
    
    if (query.next()) {
        QSqlRecord record = query.record();
        for (int i = 0; i < record.count(); ++i) {
            result[record.fieldName(i)] = record.value(i);
        }
    }
    
    return result;
}

/**
 * @brief 从指定数据库表中查询多条记录
 *
 * 根据提供的表名和查询条件，从数据库中检索匹配的记录。
 * 查询条件以键值对形式提供，将被转换为SQL WHERE子句。
 * 返回的结果是包含所有匹配记录的列表，每条记录表示为字段名到字段值的映射。
 *
 * @param tableName 要查询的数据库表名
 * @param conditions 查询条件，键值对形式的映射，键为字段名，值为匹配值
 * @return QVariantList 包含查询结果的列表，每个元素是一个QVariantMap，
 *         表示一条记录，键为字段名，值为字段值
 */
QVariantList DatabaseManager::selectRecords(const QString &tableName, const QVariantMap &conditions)
{
    QVariantList result;
    
    // 检查数据库连接状态
    if (!m_db || !m_db->isOpen()) {
        m_lastError = "数据库未初始化";
        return result;
    }
    
    // 构建SQL查询语句
    QString whereClause = buildWhereClause(conditions);
    QString sql = QString("SELECT * FROM %1").arg(tableName);
    if (!whereClause.isEmpty()) {
        sql += " WHERE " + whereClause;
    }
    
    QSqlQuery query(*m_db);
    query.prepare(sql);
    
    // 绑定查询参数
    int index = 0;
    for (auto it = conditions.constBegin(); it != conditions.constEnd(); ++it) {
        query.bindValue(index++, it.value());
    }
    
    // 执行查询并处理错误
    if (!query.exec()) {
        m_lastError = query.lastError().text();
        LOG_ERROR("查询数据失败 {}:",m_lastError.toStdString());
        return result;
    }
    
    // 处理查询结果
    while (query.next()) {
        QSqlRecord record = query.record();
        QVariantMap row;
        for (int i = 0; i < record.count(); ++i) {
            row[record.fieldName(i)] = record.value(i);
        }
        result.append(row);
    }
    
    return result;
}

/**
 * @brief 从指定表中删除符合特定条件的记录
 *
 * @param tableName 要操作的数据库表名
 * @param conditions 删除条件键值对，键为字段名，值为条件值
 * @return bool 删除操作是否成功执行
 *
 * 该函数构建DELETE SQL语句并执行，根据conditions提供的条件删除tableName表中的记录。
 * 如果数据库未连接或条件为空，则操作失败并设置相应错误信息。
 */
bool DatabaseManager::deleteRecord(const QString &tableName, const QVariantMap &conditions)
{
    // 检查数据库连接状态
    if (!m_db || !m_db->isOpen()) {
        m_lastError = "数据库未初始化";
        return false;
    }
    
    // 验证删除条件不能为空
    if (conditions.isEmpty()) {
        m_lastError = "删除条件不能为空";
        return false;
    }
    
    QString whereClause = buildWhereClause(conditions);
    QString sql = QString("DELETE FROM %1 WHERE %2").arg(tableName, whereClause);
    
    QSqlQuery query(*m_db);
    query.prepare(sql);
    
    // 绑定条件值到查询语句
    int index = 0;
    for (auto it = conditions.constBegin(); it != conditions.constEnd(); ++it) {
        query.bindValue(index++, it.value());
    }
    
    // 执行删除操作并处理错误
    if (!query.exec()) {
        m_lastError = query.lastError().text();
        LOG_ERROR("删除数据失败 {}:",m_lastError.toStdString());
        return false;
    }
    
    return true;
}

/**
 * @brief 执行自定义SQL查询
 *
 * 执行传入的SQL语句，并将查询结果以QVariantList形式返回。
 * 支持参数绑定，可以防止SQL注入攻击。
 *
 * @param sql 要执行的SQL语句
 * @param bindings SQL参数绑定值列表
 * @return QVariantList 查询结果列表，每个元素是一条记录，以字段名-值对的形式存储
 *
 * @note 如果数据库未初始化或查询执行失败，函数会返回空的QVariantList，
 *       并通过lastError()函数可以获取具体的错误信息
 */
QVariantList DatabaseManager::executeQuery(const QString &sql, const QVariantList &bindings)
{
    QVariantList result;
    
    // 检查数据库连接状态
    if (!m_db || !m_db->isOpen()) {
        m_lastError = "数据库未初始化";
        return result;
    }
    
    QSqlQuery query(*m_db);
    query.prepare(sql);
    
    // 绑定查询参数
    for (int i = 0; i < bindings.size(); ++i) {
        query.bindValue(i, bindings.at(i));
    }
    
    // 执行查询并处理错误
    if (!query.exec()) {
        m_lastError = query.lastError().text();
        LOG_ERROR("执行查询失败 {}:",m_lastError.toStdString());
        return result;
    }
    
    // 处理查询结果
    while (query.next()) {
        QSqlRecord record = query.record();
        QVariantMap row;
        for (int i = 0; i < record.count(); ++i) {
            row[record.fieldName(i)] = record.value(i);
        }
        result.append(row);
    }
    
    return result;
}


/**
 * @brief 获取最后一次数据库操作的错误信息
 * @return 返回最后一次数据库操作的错误信息字符串
 */
QString DatabaseManager::lastError() const
{
    return m_lastError;
}

/**
 * @brief 构建SQL WHERE子句
 *
 * 根据提供的条件映射构建SQL WHERE子句，每个条件使用"="比较符和参数占位符
 *
 * @param conditions 条件映射，键为字段名，值为字段值
 * @return 返回构建的WHERE子句字符串，如果条件为空则返回空字符串
 */
QString DatabaseManager::buildWhereClause(const QVariantMap &conditions)
{
    if (conditions.isEmpty()) {
        return QString();
    }
    
    QStringList clauses;
    for (auto it = conditions.constBegin(); it != conditions.constEnd(); ++it) {
        clauses << QString("%1 = ?").arg(it.key());
    }
    
    return clauses.join(" AND ");
}

/**
 * @brief 根据时间戳范围查询记录
 *
 * @param tableName 要查询的表名
 * @param timestampColumn 时间戳列名
 * @param startTimestamp 开始时间戳
 * @param endTimestamp 结束时间戳
 * @return QVariantList 查询结果列表
 */
QVariantList DatabaseManager::selectRecordsByTimestampRange(const QString &tableName, const QString &timestampColumn, const QString &startTimestamp, const QString &endTimestamp)
{
    QVariantList result;
    
    // 检查数据库连接状态
    if (!m_db || !m_db->isOpen()) {
        m_lastError = "数据库未初始化";
        return result;
    }
    
    // 构建SQL查询语句
    QString sql = QString("SELECT * FROM %1 WHERE %2 BETWEEN ? AND ? ORDER BY %2")
                     .arg(tableName, timestampColumn);
    
    QSqlQuery query(*m_db);
    query.prepare(sql);
    query.addBindValue(startTimestamp);
    query.addBindValue(endTimestamp);
    
    // 执行查询并处理错误
    if (!query.exec()) {
        m_lastError = query.lastError().text();
        LOG_ERROR("查询数据失败 {}:",m_lastError.toStdString());
        return result;
    }
    
    // 处理查询结果
    while (query.next()) {
        QSqlRecord record = query.record();
        QVariantMap row;
        for (int i = 0; i < record.count(); ++i) {
            row[record.fieldName(i)] = record.value(i);
        }
        result.append(row);
    }
    
    return result;
}